// Comms based on Curly's script, massively updated by Tursi
// triggered by eye derp!

integer HUD_CHANNEL = -841511254;       // channel for HUD communications
string UPDATE_EYES_COMMAND = "update eyes";

integer CHANGE_TIME = 15;

float nChangeTimerFps = 10;
float nDistance = 0.0;
float LightningChangeOdds = 0.35;

integer lightningnumber = 110;
integer smokenumber = 10;
float radius       = 0.32;  // Distance from emitter in meters.
float start_size   = 0.4;   // How big particles start
float end_size     = 0.2;   // How big particles finish as
vector start_color = <1.0, 1.0, 1.0>; // Start color  <R,G,B>  <1.0, 1.0, 1.0> = white
vector end_color   = <0.0, 0.0, 0.4>; // End color  <R,G,B>

integer LightningState = 0;

list lightning_parts = [ PSYS_PART_FLAGS,
//                    PSYS_PART_EMISSIVE_MASK |         0x100
//                    PSYS_PART_INTERP_COLOR_MASK |     0x001
//                    PSYS_PART_INTERP_SCALE_MASK |     0x002
//                    PSYS_PART_FOLLOW_VELOCITY_MASK,   0x020
// can't add or OR in an initializer, so this is the raw number:
                    0x123,
                PSYS_SRC_PATTERN,
                    PSYS_SRC_PATTERN_EXPLODE,
                PSYS_SRC_BURST_RATE, 0.01,
                PSYS_PART_START_COLOR, start_color,
                PSYS_PART_END_COLOR, end_color,
                PSYS_SRC_BURST_RADIUS, radius,
                PSYS_PART_START_SCALE, <start_size, start_size, start_size>,
                PSYS_PART_END_SCALE, <end_size, end_size, end_size>,
                PSYS_PART_START_ALPHA, 1.0,
                PSYS_PART_END_ALPHA, 0.05,
                PSYS_PART_MAX_AGE, 0.01,
                PSYS_SRC_TEXTURE, "dd36368c-4e66-873b-1a47-d5b683ad4136",   // lightning
                PSYS_SRC_BURST_SPEED_MAX, 0.03,
                PSYS_SRC_BURST_SPEED_MIN, 0.03
            ];

// Convert a key to an integer using the first 8 hex digits (32 bits)
integer key2integer(key k) {
    return (integer)("0x" + llGetSubString((string)k, 0, 7));
}

integer channel() {
    return HUD_CHANNEL ^ key2integer(llGetOwner());
}

float ProcessListen(key id, string msg) {
    if (llGetOwnerKey(id) != llGetOwner()) return -1;
        
    list parsed  = llParseString2List(msg, [";"], []);
    string command = llList2String(parsed, 0);
    
//  llOwnerSay("Got command: " + (string)parsed);

    if (command == UPDATE_EYES_COMMAND) {
        integer i;
        for (i = 1; i < llGetListLength(parsed); i+=2) {
            string param = llList2String(parsed, i);
            float  value = (float)llList2String(parsed, i+1);
            if (param == "derprange") {
                return value;
            }
        }
    }
    
    return -1;
}

ProcessFade() {
    if (nDistance > 0.5) {
        // fade this prim into view
        float fade=(nDistance-0.5)*2.0;
        if (fade > 0.99) fade=0.99;     // don't go full solid yet, it makes the smoke particles look awful
        ChangeAllPrims(fade);
    } else {
        // no action - leave prim transparent
        ChangeAllPrims(0.0);
    }
}

ResetState() {
    llListen(channel(), "", NULL_KEY, "");
    llParticleSystem([]);
    LightningState=0;
}

// assumes up to 4 prims (for the hind legs)
ChangeAllPrims(float alpha) {
    llSetLinkAlpha(1, alpha, ALL_SIDES);
    llSetLinkAlpha(2, alpha, ALL_SIDES);
    llSetLinkAlpha(3, alpha, ALL_SIDES);
    llSetLinkAlpha(4, alpha, ALL_SIDES);
}

// luna state
default
{
    state_entry()
    {
        // default to Luna
        ResetState();
        ChangeAllPrims(0.0);   // transparent
    }

//    touch_start(integer x) {
//        llSay(channel(),"update eyes;derprange;.80");
//        state goNightmare;
//    }

    listen(integer channel, string name, key id, string msg) {
        if (ProcessListen(id, msg) > 0.75) {
            state goNightmare;
        }
    }
}

state goNightmare
{
    state_entry()
    {
        llSetTimerEvent(1.0/nChangeTimerFps);
        nDistance = 0.0;
        llParticleSystem(lightning_parts + [PSYS_SRC_BURST_PART_COUNT, 10]);
        LightningState=1;
    }
    
    timer() 
    {
        nDistance+=1.0/(CHANGE_TIME*nChangeTimerFps);
        if (nDistance >= 1.3) {
            // done, complete transition
            state Nightmare;
        } else if (nDistance >= 1.0) {
            // just hold off here a little longer for the particles to stop
            // before we go full solid
        } else {
            ProcessFade();
        }
        if (llFrand(1.0) <= LightningChangeOdds) {
            if (LightningState) {
                LightningState = 0;
                llParticleSystem([]);
            } else {
                LightningState = 1;
                llParticleSystem(lightning_parts + [PSYS_SRC_BURST_PART_COUNT, 10]);
            }
        }
    }
}

state Nightmare
{
    state_entry()
    {
        ResetState();
        llListen(channel(), "", NULL_KEY, "");
        ChangeAllPrims(1.0);
    }
    
//    touch_start(integer x) {
//        llSay(channel(),"update eyes;derprange;.50");
//        state goLuna;
//    }

    listen(integer channel, string name, key id, string msg) {
        float x = ProcessListen(id, msg);
        if ((x > 0) && (x < 0.55)) {
            state goLuna;
        }
    }
}    

state goLuna
{
    state_entry()
    {
        llSetTimerEvent(1.0/nChangeTimerFps);
        nDistance = 1.0;
    }
    
    timer() 
    {
        nDistance-=1.0/(CHANGE_TIME*nChangeTimerFps);
        if (nDistance <= 0.0) {
            // done, complete transition
            state default;
        } else {
            ProcessFade();
        }
    }
}
